/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pfc.arbol;

import java.awt.Component;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.io.FileUtils;
import org.apache.ddlutils.model.Database;
import pfc.modeloer.ERModel;
import pfc.comun.IDEpfc;
import pfc.comun.Proyecto;
import pfc.generacion.Application;
import pfc.generacion.ApplicationManager;
import pfc.gui.PropertiesEdit;
import pfc.modelocg.CGModel;
import pfc.modelocg.CGModelIO;
import pfc.utils.Utils;

/**
 *
 * @author xandru
 */
public class ProyectoTreeNode extends PFCTreeNode {

    ApplicationManager _appManager;
    FolderTreeNode _appsFolder;

    public ProyectoTreeNode(Proyecto pro, String nombre) {
        super(pro, nombre);

        this.proyecto = pro;
    }

    public String getNombre() {
        return proyecto.nombre;
    }

    public void setNombre(String nombre) {
        this.proyecto.nombre = nombre;
    }

    public String getpath() {
        return proyecto.path;
    }

    public void setPath(String path) {
        this.proyecto.path = path;
    }

    @Override
    protected void construirMenuContexto() {
        super.construirMenuContexto();

        final ProyectoTreeNode nodo = this;

        File fds = new File(this.dsFile);
        File fdm = new File(this.dbModelFile);
        File fer = new File(this.entityModelFile);
        File fgc = new File(this.codeGenerationFile);


        JMenuItem mi = new JMenuItem("Añadir Origen de Datos");
        popupMenu.add(mi);
        mi.setEnabled(!fds.exists());
        mi.setActionCommand("addDataSource");
        mi.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent e) {
                PropertiesEdit dsProperties = null;
                try {
                    PropertiesConfiguration conf = new PropertiesConfiguration();
                    conf.addProperty("driver", "");
                    conf.addProperty("url", "");
                    conf.addProperty("usuario", "");
                    conf.addProperty("password", "");

                    conf.save(dsFile);
                    conf = new PropertiesConfiguration(dsFile);
                    dsProperties = new PropertiesEdit(conf);
                } catch (ConfigurationException ex) {
                    Logger.getLogger(DBTreeNode.class.getName()).log(Level.SEVERE, null, ex);
                    System.out.println(ex.getMessage());
                }
                IDEpfc.app.addParaEditar(dsProperties, "Origen de Datos");

                DataSourceTreeNode ds = new DataSourceTreeNode(proyecto, "Origen Datos");
                add(ds);
                enableMenu();

                IDEpfc.refreshTree(nodo);
            }
        });


        mi = new JMenuItem("Obtener Modelo de Datos");
        mi.setActionCommand("getDataModel");
        popupMenu.add(mi);
        mi.setEnabled(fds.exists() && !fdm.exists());
        mi.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent e) {
                IDEpfc.logTime("Obteniendo modelo de datos para el proyecto " + proyecto.nombre);
                PropertiesConfiguration conf = null;
                try {
                    conf = new PropertiesConfiguration(dsFile);
                } catch (ConfigurationException ex) {
                    Logger.getLogger(DBTreeNode.class.getName()).log(Level.SEVERE, null, ex);
                }

                
                Database dbModel = Utils.getDatabaseModel(conf);
                Utils.modelToXML(dbModel, dbModelFile);

                DBTreeNode db = new DBTreeNode(proyecto,"Modelo Datos");
                add(db);

                DataModelTreeNode dm = new DataModelTreeNode(proyecto,"base");
                dm.setDBModel(dbModel);
                db.add(dm);
               
                //DataModelTreeNode dmtn = new DataModelTreeNode(proyecto, "Modelo Datos");
                //add(dmtn);

                enableMenu();

                IDEpfc.refreshTree(nodo);
                IDEpfc.logTime("Modelo de datos obtenido correctamente en " + dbModelFile);
            }
        });


        final JMenuItem mer = new JMenuItem("Obtener Modelo Entidad-Relacion");
        mer.setActionCommand("getERModel");

        mer.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent e) {
                obtainERModel();
            }
        });
        popupMenu.add(mer);
        mer.setEnabled(fds.exists() && fdm.exists() && !fer.exists());



        mi = new JMenuItem("Obtener Modelo Generacion Codigo");
        mi.setActionCommand("getCGModel");
        popupMenu.add(mi);
        mi.setEnabled(fds.exists() && fdm.exists() && fer.exists() && !fgc.exists());
        mi.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent e) {
                obtainCGModel();
            }
        });

        mi = new JMenuItem("Nueva Aplicacion");
        mi.setActionCommand("newApplication");
        popupMenu.add(mi);
        mi.setEnabled(fgc.exists());
        mi.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent e) {
                crearAplicacion();
            }
        });


        mi = new JMenuItem("Eliminar Proyecto");
        mi.setActionCommand("deleteProject");
        popupMenu.add(mi);
        mi.setEnabled(true);
        mi.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent e) {
                //JDialog dialogo = new JDialog();
                //dialogo.setModal(true);
                //dialogo.setVisible(true);
                int borrar = JOptionPane.showConfirmDialog(IDEpfc.app, "Esta accion provocara la eliminacion de todo el proyecto ¿desea continuar?");
                if (borrar == JOptionPane.OK_OPTION) {
                    borrarProyecto();
                }
            }
        });

    }

    private void obtainERModel() {
        IDEpfc.logTime("Obteniendo modelo Entidad-Relacion para el proyecto " + proyecto.nombre);
        Database db = Utils.XMLtoModel(dbModelFile);
        ERModel er = new ERModel(db);

        ERModelTreeNode en = (ERModelTreeNode) findFirstChild(ERModelTreeNode.class);

        Utils.modelToXML(er, entityModelFile);
        if (en != null) {
            this.remove(en);
        }

        en = new ERModelTreeNode(proyecto, "Modelo E-R");
        en.buildTree(er);

        DBTreeNode dbn = findDBTreeNode();


        dbn.add(en);

        IDEpfc.refreshTree(this);
        enableMenu();
        IDEpfc.logTime("Modelo Entidad-Relacion obtenido correctamente en " + entityModelFile);

    }

    private void obtainCGModel() {

        IDEpfc.logTime("Obteniendo modelo Generacion de Codigo para el proyecto " + proyecto.nombre);
        CGTreeNode node = new CGTreeNode(proyecto, "Modelo Generacion Codigo");
        Database db = Utils.XMLtoModel(dbModelFile);
        ERModel er = Utils.XMLToERModel(entityModelFile);
        er.update(db);
        CGModel cg = new CGModel(er, db);

        CGModelIO.model2XML(cg, this.codeGenerationFile);

        node.buildTree(cg, er, db);

        this.add(node);


        IDEpfc.refreshTree(this);
        enableMenu();
        IDEpfc.logTime("Modelo de Generacion de Codigo obtenido correctamente en " + codeGenerationFile);
    }

    @Override
    public void click(MouseEvent e) {
        //int selRow =  jtArbolProyectos.getRowForLocation(evt.getX(), evt.getY());
        // TreePath selPath = jtArbolProyectos.getPathForLocation(evt.getX(), evt.getY());
        // if(selRow != -1) {

        if (e.getButton() == MouseEvent.BUTTON3) {
            System.out.println(popupMenu);
            mostrarMenuContexto(e);

        }
        if (e.getClickCount() == 1) {
            System.out.println("Click " + this.getClass().getName() + e.getButton());
        } else if (e.getClickCount() == 2) {
            System.out.println("DoubleClick " + this.getClass().getName());
        }


    }

    private void enableMenu() {
        File fds = new File(this.dsFile);
        File fdm = new File(this.dbModelFile);
        File fer = new File(this.entityModelFile);
        File fgc = new File(this.codeGenerationFile);

        for (Component c : popupMenu.getComponents()) {
            if (c.getClass() == JMenuItem.class) {
                JMenuItem i = (JMenuItem) c;
                if (i.getActionCommand().equals("addDataSource")) {
                    i.setEnabled(!fds.exists());
                }
                ;
                if (i.getActionCommand().equals("getDataModel")) {
                    i.setEnabled( !fdm.exists() && fds.exists() );
                }
                ;
                if (i.getActionCommand().equals("getERModel")) {
                    i.setEnabled( !fer.exists() && fdm.exists() );
                }
                ;
                if (i.getActionCommand().equals("getCGModel")) {
                    i.setEnabled( !fgc.exists() && fer.exists() );
                }
                ;
                if (i.getActionCommand().equals("newApplication")) {
                    i.setEnabled(fgc.exists());
                }
                ;
            }
        }
    }

    private void crearAplicacion() {


        if (this._appManager == null) {
            _appManager = new ApplicationManager(this, this.proyecto);
            _appsFolder = new FolderTreeNode(this.proyecto, "Aplicaciones");
            this.add(_appsFolder);
        }

        Application app = this._appManager.newApplication(_appsFolder.getChildCount());

        IDEpfc.logTime("Creando la aplicacion " + app.getName() + " en " + app.getPath());

        ApplicationTreeNode atn = new ApplicationTreeNode(this.proyecto, app);
        _appsFolder.add(atn);
        IDEpfc.refreshTree(this);


        
//        IDEpfc.addFileTreeApplication(app,proyecto);


        CGTreeNode nodo = null;
        for (Enumeration e = this.children(); e.hasMoreElements();) {
            TreeNode t = (TreeNode) e.nextElement();

            if (t.getClass() == CGTreeNode.class) {
                //System.out.println("Es un nodo de tipo CGTreeNode" );
                nodo = (CGTreeNode) t;
            }

        }

        nodo.reloadModels();

        app.generate(this.proyecto, nodo.getDbModel(), nodo.getErModel(), nodo.getCgModel());

        IDEpfc.app.initArbolFicheros();
    }

    public ApplicationManager getAppManager() {
        return _appManager;
    }

    public void setAppManager(ApplicationManager _appManager) {
        this._appManager = _appManager;
    }

    public FolderTreeNode getAppsFolder() {
        return _appsFolder;
    }

    public void setAppsFolder(FolderTreeNode _appsFolder) {
        this._appsFolder = _appsFolder;
    }

    public Database getDatabase() {
        CGTreeNode n = getCGTreeNode();
        n.reloadModels();
        return n.getDbModel();
    }

    public ERModel getERModel() {
        CGTreeNode n = getCGTreeNode();
        n.reloadModels();
        return n.getErModel();
    }

    public CGModel getCGModel() {
        CGTreeNode n = getCGTreeNode();
        n.reloadModels();
        return n.getCGModel();
    }

    private CGTreeNode getCGTreeNode() {
        CGTreeNode nodo = null;
        for (Enumeration e = this.children(); e.hasMoreElements();) {
            TreeNode t = (TreeNode) e.nextElement();
            if (t.getClass() == CGTreeNode.class) {
                //System.out.println("Es un nodo de tipo CGTreeNode" );
                nodo = (CGTreeNode) t;
            }
        }

        return nodo;
    }

    private void borrarProyecto() {
        try {
            FileUtils.deleteDirectory(new File(this.proyecto.path));
            DefaultMutableTreeNode p = (DefaultMutableTreeNode) this.getParent();
            p.remove(this);
            IDEpfc.refreshTree(p);
            IDEpfc.logTime("Proyecto eliminado " + this.proyecto.nombre + " del directorio " + this.proyecto.path);

        } catch (IOException ex) {
            Logger.getLogger(ProyectoTreeNode.class.getName()).log(Level.SEVERE, null, ex);
            JOptionPane.showMessageDialog(IDEpfc.app, "No se ha podido borrar el proyecto " + ex.getMessage());
        }

    }

    private DBTreeNode findDBTreeNode() {
        for (int i=0;i<this.getChildCount();i++)
        {
            TreeNode n = this.getChildAt(i);
            if (n.getClass() == DBTreeNode.class)
                return (DBTreeNode) n;
        }
        return null;
    }
}
